package com.onpositive.gamemaker.treeview;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import com.onpositive.gamemaker.editor.GameCreatorEditorPlugin;

/**
 * This class provides the labels for the file tree
 */

class FileTreeLabelProvider implements ILabelProvider
{

	protected static final String DEFAULT_FILE_IMAGE_PATH = "icons/file.gif";
	protected static final String DEFAULT_DIR_IMAGE_PATH = "icons/dir.gif";

	protected static Image defaultFileIcon;
	protected static Image defaultDirIcon;
	// The listeners
	protected List<ILabelProviderListener> listeners;
	protected Map <String, Image> extensionImages;
	


	// Label provider state: preserve case of file names/directories
	boolean preserveCase = true;

	/**
	 * Constructs a FileTreeLabelProvider
	 */
	public FileTreeLabelProvider()
	{
		// Create the list to hold the listeners
		listeners = new ArrayList<ILabelProviderListener>();
		extensionImages = new HashMap<String, Image>();
	}

	/**
	 * Sets the preserve case attribute
	 * 
	 * @param preserveCase
	 *            the preserve case attribute
	 */
	public void setPreserveCase(boolean preserveCase)
	{
		this.preserveCase = preserveCase;

		// Since this attribute affects how the labels are computed,
		// notify all the listeners of the change.
		LabelProviderChangedEvent event = new LabelProviderChangedEvent(this);
		for (int i = 0, n = listeners.size(); i < n; i++)
		{
			ILabelProviderListener ilpl = (ILabelProviderListener) listeners.get(i);
			ilpl.labelProviderChanged(event);
		}
	}

	protected static Image getDefaultFileIcon()
	{
		if (defaultFileIcon == null)
		{
			defaultFileIcon = AbstractUIPlugin.imageDescriptorFromPlugin(GameCreatorEditorPlugin.PLUGIN_ID, DEFAULT_FILE_IMAGE_PATH).createImage();
		}
		return defaultFileIcon;
	}

	protected static Image getDefaultDirIcon()
	{
		if (defaultDirIcon == null)
		{
			defaultDirIcon = AbstractUIPlugin.imageDescriptorFromPlugin(GameCreatorEditorPlugin.PLUGIN_ID, DEFAULT_DIR_IMAGE_PATH).createImage();
		}
		return defaultDirIcon;
	}

	/**
	 * Gets the image to display for a node in the tree
	 * 
	 * @param arg0
	 *            the node
	 * @return Image
	 */
	public Image getImage(Object arg0)
	{
		File file = (File) arg0;
		// If the node represents a directory, return the directory image.
		// Otherwise, return the file image.
		if (file.isDirectory())
			return getDefaultDirIcon();
		else
		{
			String extension = getExtension(file);
			Image icon = tryToGetIcon(extension);
			if (icon != null)
				return icon;
		}
		return getDefaultFileIcon();
	}

	protected Image tryToGetIcon(String extension)
	{
		if (extension == null || extension.length() == 0)
			return null;
		extension = extension.toLowerCase();
		Image current = extensionImages.get(extension);
		if (current != null)
			return current;
		else
		{
			Program p = Program.findProgram (extension);
			if (p != null) {
				ImageData data = p.getImageData ();
				if (data != null) {
					Image image = new Image (Display.getDefault(), data);
					extensionImages.put(extension, image);
				}
			} else 
			{
				try
				{
					IEditorDescriptor editorDescriptor = IDE.getEditorDescriptor(extension);
					if (editorDescriptor != null)
					{
						ImageDescriptor imageDescriptor = editorDescriptor.getImageDescriptor();
						if (imageDescriptor != null)
							extensionImages.put(extension, imageDescriptor.createImage());
					}
				} catch (PartInitException e)
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	protected String getExtension(File file)
	{
		String name = file.getName();
		int idx = name.lastIndexOf('.');
		if (idx > 0)
			return name.substring(idx);
		return null;
	}

	/**
	 * Gets the text to display for a node in the tree
	 * 
	 * @param arg0
	 *            the node
	 * @return String
	 */
	public String getText(Object arg0)
	{
		// Get the name of the file
		String text = ((File) arg0).getName();

		// If name is blank, get the path
		if (text.length() == 0)
		{
			text = ((File) arg0).getPath();
		}

		// Check the case settings before returning the text
		return preserveCase ? text : text.toUpperCase();
	}

	/**
	 * Adds a listener to this label provider
	 * 
	 * @param arg0
	 *            the listener
	 */
	public void addListener(ILabelProviderListener arg0)
	{
		listeners.add(arg0);
	}

	/**
	 * Called when this LabelProvider is being disposed
	 */
	public void dispose()
	{
		// Dispose the images
		if (getDefaultDirIcon() != null)
			getDefaultDirIcon().dispose();
		if (getDefaultFileIcon() != null)
			getDefaultFileIcon().dispose();
	}

	/**
	 * Returns whether changes to the specified property on the specified
	 * element would affect the label for the element
	 * 
	 * @param arg0
	 *            the element
	 * @param arg1
	 *            the property
	 * @return boolean
	 */
	public boolean isLabelProperty(Object arg0, String arg1)
	{
		return false;
	}

	/**
	 * Removes the listener
	 * 
	 * @param arg0
	 *            the listener to remove
	 */
	public void removeListener(ILabelProviderListener arg0)
	{
		listeners.remove(arg0);
	}
}